﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraBars;
using XCI.Windows.Core;
using XCI.Helper;
using XCI.Extensions;
using XCI.Windows.Helper;
using XCI.Core;
using XCI.Sys.Service;
using System.IO;
using XCI.Windows.Forms;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Views.WinExplorer;
using XCI.Sys.Core;
using DevExpress.Utils.Helpers;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;
using DevExpress.XtraGrid;
using DevExpress.Data;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.Utils;
using System.Linq;
using DevExpress.XtraGrid.Views.WinExplorer.ViewInfo;
using DevExpress.XtraEditors;
using System.Threading.Tasks;
using XCI.Sys.Model;
using System.Diagnostics;

namespace XCI.Sys.Controls
{
    public partial class FileUploadControl : UserControl
    {
        private readonly List<UploadFile> data = new List<UploadFile>();
        private const string ALLOW_EXTENSION_NAME = "gif,jpg,jpeg,png,bmp,zip,rar,doc,docx,xls,xlsx,ppt,pptx,txt,pdf,repx";
        const string boolMessageSeparator = "\n";
        private long totalSize = 0;
        private long totalCount = 0;
        private string editValue;
        private FileUploadGridViewMode viewMode = FileUploadGridViewMode.GridView;

        public FileUploadControl()
        {
            InitializeComponent();
            //openFile.Filter = "PNG文件 (*.png)|*.png|GIF文件 (*.gif)|*.gif|JPEG文件 (*.jpg;*.jpeg)|*.jpg;*.jpeg|所有图像文件 |*.bmp;*.gif;*.jpg;*.jpeg;*.png;|所有文件 |*.*";
            //saveFile.Filter = "PNG文件 (*.png)|*.png|GIF文件 (*.gif)|*.gif|JPEG 文件 (*.jpg)|*.jpg|位图文件 (*.bmp)|*.bmp";
        }

        /// <summary>
        /// 行视图
        /// </summary>
        [Browsable(false), Category("XCI控件"), Description("行视图")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public GridView GridView => gridView1;

        /// <summary>
        /// 图片视图
        /// </summary>
        [Browsable(false), Category("XCI控件"), Description("图片视图")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public WinExplorerView ExplorerView => explorerView1;

        /// <summary>
        /// Bar控件
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public BarManager BarControl => barManager1;

        /// <summary>
        /// 工具条控件
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Bar ToolBarControl => bar1;

        /// <summary>
        /// 等待面板
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public XCIOverlayForm OverlayForm { get; } = new XCIOverlayForm();

        /// <summary>
        /// 是否显示工具栏
        /// </summary>
        [Browsable(true), Category("XCI按钮"), Description("是否显示工具栏")]
        public bool ToolbarVisable { get; set; } = true;

        /// <summary>
        /// 视图模式
        /// </summary>
        [Browsable(true), Category("XCI按钮"), Description("视图模式"), DefaultValue(FileUploadGridViewMode.GridView)]
        public FileUploadGridViewMode ViewMode
        {
            get => viewMode;
            set
            {
                viewMode = value;
                SetViewMode(value);
            }
        }

        /// <summary>
        /// 选择按钮
        /// </summary>
        [Browsable(true), Category("XCI按钮"), Description("选择按钮")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public BarButtonItem SelectButton
        {
            get => btnSelect;
        }

        /// <summary>
        /// 移除按钮
        /// </summary>
        [Browsable(true), Category("XCI按钮"), Description("移除按钮")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public BarButtonItem RemoveButton
        {
            get => btnRemove;
        }

        /// <summary>
        /// 上传按钮
        /// </summary>
        [Browsable(true), Category("XCI按钮"), Description("上传按钮")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public BarButtonItem UploadButton
        {
            get => btnUpload;
        }

        /// <summary>
        /// 导出按钮
        /// </summary>
        [Browsable(true), Category("XCI按钮"), Description("导出按钮")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public BarButtonItem ExportButton
        {
            get => btnExport;
        }

        /// <summary>
        /// 切换视图按钮
        /// </summary>
        [Browsable(true), Category("XCI按钮"), Description("切换视图按钮")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public BarButtonItem SwitchViewButton
        {
            get => btnSwitchView;
        }

        /// <summary>
        /// 上传子文件夹（默认自动获取）
        /// </summary>
        [Browsable(true), Category("XCI上传"), Description("上传子文件夹（默认自动生成）")]
        public string UploadFolder { get; set; }

        /// <summary>
        /// 上传成功后保存到附件表
        /// </summary>
        [Browsable(true), Category("XCI上传"), Description("上传成功后保存到附件表"), DefaultValue(true)]
        public bool AutoSaveToFileTable { get; set; } = true;

        /// <summary>
        /// 是否允许添加目录
        /// </summary>
        [Browsable(true), Category("XCI上传"), Description("是否允许添加目录"), DefaultValue(true)]
        public bool AllowAddFolder { get; set; } = true;

        /// <summary>
        /// 是否允许添加快捷方式
        /// </summary>
        [Browsable(true), Category("XCI上传"), Description("是否允许添加快捷方式"), DefaultValue(true)]
        public bool AllowAddShortcut { get; set; } = true;

        /// <summary>
        /// 获取或设置记录主键。
        /// </summary>
        [Category("Data"), Description("获取或设置记录主键。")]
        [Browsable(false), Bindable(true), DefaultValue(null)]
        public string EditValue
        {
            get { return editValue; }
            set
            {
                editValue = value;
                LoadFile(editValue);
            }
        }

        /// <summary>
        /// 是否需要上传
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool RequiredUpload
        {
            get
            {
                return data.Any(p => p.Status == FileUploadStatus.Waiting);
            }
        }

        /// <summary>
        /// 允许文件上传的扩展名,不含点,逗号隔开
        /// </summary>
        [Category("XCI属性"), Description("许文件上传的扩展名,不含点,逗号隔开"), DefaultValue(ALLOW_EXTENSION_NAME)]
        public string AllowFileExtension { get; set; } = ALLOW_EXTENSION_NAME;

        /// <summary>
        /// 最多允许的文件数量
        /// </summary>
        [Category("XCI属性"), Description("最多允许的文件数量"), DefaultValue(99)]
        public int MaxFileCount { get; set; } = 99;

        /// <summary>
        /// 单个文件允许的最大值,单位KB,默认10M
        /// </summary>
        [Category("XCI属性"), Description("单个文件允许的最大值,单位KB,默认10M"), DefaultValue(10240)]
        public int SingleFileMaxSize { get; set; } = 10240;


        [Category("XCI事件"), Description("文件加载前事件")]
        public event EventHandler<FileBeforeEventArgs> BeforeLoad;

        [Category("XCI事件"), Description("文件加载完成事件")]
        public event EventHandler<FileEventArgs> LoadCompleted;

        [Category("XCI事件"), Description("文件选择前事件")]
        public event EventHandler<FileBeforeEventArgs> BeforeSelect;

        [Category("XCI事件"), Description("文件选择完成事件")]
        public event EventHandler<FileEventArgs> SelectCompleted;

        [Category("XCI事件"), Description("文件移除前事件")]
        public event EventHandler<FileBeforeEventArgs> BeforeRemove;

        [Category("XCI事件"), Description("文件移除完成事件")]
        public event EventHandler<FileEventArgs> RemoveCompleted;

        [Category("XCI事件"), Description("文件导出前事件")]
        public event EventHandler<FileBeforeEventArgs> BeforeExport;

        [Category("XCI事件"), Description("文件导出完成事件")]
        public event EventHandler<FileEventArgs> ExportCompleted;

        [Category("XCI事件"), Description("文件上传前事件")]
        public event EventHandler<FileBeforeEventArgs> BeforeUpload;

        [Category("XCI事件"), Description("文件上传完成事件")]
        public event EventHandler<FileUploadEventArgs> UploadCompleted;

        /// <summary>
        /// 生成右键菜单
        /// </summary>
        private void BuildPopupMenuCore()
        {
            foreach (BarItem item in barManager1.Items)
            {
                if (!(item is BarButtonItem)) continue;
                popupMenu1.ItemLinks.Add(item);
            }
        }

        /// <summary>
        /// 设置按钮状态
        /// </summary>
        private void SetButtonStatus()
        {
            ColumnView view = (ColumnView)gridControl1.FocusedView;
            var selectedRowCount = view.GetSelectedRows().Length;

            btnRemove.Enabled = selectedRowCount > 0;
            btnUpload.Enabled = data.Any(p => p.Status == FileUploadStatus.Waiting);
            btnExport.Enabled = selectedRowCount > 0;
            btnProperty.Enabled = selectedRowCount == 1;
        }

        private void SetViewMode(FileUploadGridViewMode viewMode)
        {
            switch (viewMode)
            {
                case FileUploadGridViewMode.GridView:
                    gridControl1.MainView = gridView1;
                    break;
                case FileUploadGridViewMode.ExplorerView:
                    gridControl1.MainView = explorerView1;
                    explorerView1.OptionsViewStyles.ExtraLarge.ImageSize = new Size(96, 96);
                    break;
            }
        }

        /// <summary>
        /// 加载文件
        /// </summary>
        /// <param name="recordId">记录主键</param>
        public void LoadFile(string recordId)
        {
            var args = new ImageBeforeEventArgs();
            BeforeLoad?.Invoke(this, args);
            if (args.Cancel)
            {
                return;
            }

            OverlayForm.Show(this);
            OverlayForm.SetText("正在加载...");
            Task.Run(() =>
            {
                var fileList = FileService.Instance.SelectListByRecordId(recordId);
                data.Clear();
                foreach (var item in fileList)
                {
                    AddServerFile(item);
                }
            }).ContinueWith(p =>
            {
                gridControl1.RefreshDataSource();
                SetButtonStatus();
                LoadCompleted?.Invoke(this, new ImageEventArgs());
                OverlayForm.Close();
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }

        /// <summary>
        /// 添加手动文件
        /// </summary>
        /// <param name="paths">文件路径数组</param>
        /// <param name="status">文件状态</param>
        private void AddFile(string[] paths, FileUploadStatus status)
        {
            try
            {
                OverlayForm.Show(this);
                OverlayForm.SetText("正在加载...");

                var result = new BoolMessage(true);
                foreach (var path in paths)
                {
                    if (path.IsEmpty()) continue;

                    var fileInfo = new FileInfo(path);
                    var isDir = (fileInfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory;
                    if (!AllowAddFolder && isDir)
                    {
                        result = result.Merge(new BoolMessage(false, "不允许添加目录"), boolMessageSeparator);
                        continue;
                    }
                    var isShortcut = IOHelper.IsShortcut(path);
                    if (!AllowAddShortcut && isShortcut)
                    {
                        result = result.Merge(new BoolMessage(false, "不允许添加快捷方式文件"), boolMessageSeparator);
                        continue;
                    }

                    if (isDir)
                    {
                        var files = IOHelper.GetFiles(path);
                        if ((data.Count + files.Length) > MaxFileCount)
                        {
                            result = new BoolMessage(false, $"已超过允许的最大数量{MaxFileCount}");
                            break;
                        }
                        foreach (var file in files)
                        {
                            var _r = AddFileCore(file, status);
                            result = result.Merge(_r, boolMessageSeparator);
                        }
                    }
                    else if (isShortcut)
                    {
                        var _r = AddFileCore(IOHelper.GetShortcutPath(path), status);
                        result = result.Merge(_r, boolMessageSeparator);
                    }
                    else
                    {
                        var _r = AddFileCore(fileInfo.FullName, status);
                        result = result.Merge(_r, boolMessageSeparator);
                    }
                }
                gridControl1.RefreshDataSource();
                if (!result.Success)
                {
                    OverlayForm.Close();
                    MessageBoxHelper.ShowError(StringHelper.GetStringByRow(result.Msg, 10));
                }
            }
            catch (Exception ex)
            {
                MessageBoxHelper.ShowError("添加文件时出错");
                DebugHelper.Catch("添加文件时出错:" + ex.Message);
            }
            finally
            {
                SetButtonStatus();
                OverlayForm.Close();
            }
        }

        private BoolMessage AddFileCore(string path, FileUploadStatus status)
        {
            var fileInfo = new FileInfo(path);
            if (!fileInfo.Exists)
            {
                return new BoolMessage(false, $"文件：{fileInfo.FullName} 不存在，无法添加");
            }
            if (string.IsNullOrEmpty(fileInfo.Extension))
            {
                return new BoolMessage(false, $"文件：{fileInfo.FullName} 没有扩展名，无法添加");
            }
            if (data.Any(p => p.Path.Equals(path.ToLower())))
            {
                return new BoolMessage(false, $"文件：{fileInfo.FullName} 已存在，无需重复添加");
            }
            if (data.Count >= MaxFileCount)
            {
                return new BoolMessage(false, $"添加的文件已超过允许数量{MaxFileCount}，无法添加");
            }
            if ((fileInfo.Length / 1024) >= SingleFileMaxSize)
            {
                return new BoolMessage(false, $"文件：{fileInfo.FullName} 文件大小({StringHelper.GetSpaceSizeString(fileInfo.Length)})超过了允许的最大值({StringHelper.GetSpaceSizeString(SingleFileMaxSize * 1024)})，无法添加");
            }
            AllowFileExtension = AllowFileExtension ?? string.Empty;
            var fileExtensions = AllowFileExtension.SplitToArray();
            if (!fileExtensions.Any(p => p.Trim().ToLower() == fileInfo.Extension.Trim().Substring(1).ToLower()))
            {
                return new BoolMessage(false, $"文件：{fileInfo.FullName} 不允许添加的扩展名。只允许{fileExtensions.JoinString()}格式");
            }

            var viewStyle = explorerView1.OptionsView.Style;
            UploadFile item = new UploadFile();
            item.Name = Path.GetFileNameWithoutExtension(path);
            item.ExtName = Path.GetExtension(path);
            item.Path = path.ToLower();
            SetFileImage(item, fileInfo);
            item.Status = status;
            data.Insert(0, item);
            return new BoolMessage(true);
        }

        private BoolMessage AddServerFile(SysFile sysFile)
        {
            var localPath = WinHelper.BuildLocalPathByServerPath(sysFile.Url);
            var fileInfo = new FileInfo(localPath);
            UploadFile item = new UploadFile();
            item.Name = Path.GetFileNameWithoutExtension(sysFile.Name);
            item.ExtName = Path.GetExtension(localPath);
            item.Path = localPath.ToLower();
            item.Percentage = 100;
            item.Status = FileUploadStatus.Finished;
            SetFileImage(item, fileInfo);
            if (sysFile.FileSize.HasValue)
            {
                item.Size = sysFile.FileSize.Value;
            }
            item.ServerFileModel = new FileModel
            {
                Id = sysFile.Id,
                Name = sysFile.Name,
                Size = sysFile.FileSize,
                Url = sysFile.Url,
                ContentType = sysFile.ContentType,
                Md5 = sysFile.Md5,
            };
            data.Add(item);
            return new BoolMessage(true);
        }

        private void SetFileImage(UploadFile uploadFile, string path)
        {
            var fileInfo = new FileInfo(path);
            SetFileImage(uploadFile, fileInfo);
        }

        private void SetFileImage(UploadFile uploadFile, FileInfo fileInfo)
        {
            IconSizeType sizeType = IconSizeType.Large;
            Size itemSize = new Size(64, 64);
            if (gridControl1.FocusedView is WinExplorerView)
            {
                sizeType = IconSizeType.ExtraLarge;
                itemSize = new Size(96, 96);
            }
            if (fileInfo.Exists)
            {
                var path = fileInfo.FullName;
                uploadFile.IsImageFile = ImageHelper.IsImage(path);
                uploadFile.Size = fileInfo.Length;
                if (uploadFile.IsImageFile)
                {
                    uploadFile.Image = ImageHelper.LoadImage(path);
                }
                else
                {
                    uploadFile.Image = FileSystemHelper.GetImage(path, sizeType, itemSize);
                }
            }
            else if (fileInfo.Extension.IsNotEmpty())//默认图片
            {
                uploadFile.Image = ImageHelper.GetFileIcon(fileInfo.Extension, true).ToBitmap(); ;
            }
        }

        /// <summary>
        /// 选择文件
        /// </summary>
        public void SelectFile()
        {
            var args = new ImageBeforeEventArgs();
            BeforeSelect?.Invoke(this, args);
            if (args.Cancel)
            {
                return;
            }

            if (this.openFile.ShowDialog() != DialogResult.OK) return;
            if (this.openFile.FileNames.Length <= 0) return;

            try
            {
                btnSelect.Enabled = false;
                AddFile(openFile.FileNames, FileUploadStatus.Waiting);
                SelectCompleted?.Invoke(this, new ImageEventArgs());
            }
            finally
            {
                btnSelect.Enabled = true;
            }
        }

        /// <summary>
        /// 移除文件
        /// </summary>
        public void RemoveFile()
        {
            var args = new ImageBeforeEventArgs();
            BeforeRemove?.Invoke(this, args);
            if (args.Cancel)
            {
                return;
            }

            if (MessageBoxHelper.ShowMessageYesNo("确定要移除选中的文件吗？") != DialogResult.Yes) return;
            try
            {
                var selectedList = GetSelectedList();
                ColumnView view = (ColumnView)gridControl1.FocusedView;
                //if (selectedList.Count == 0 && view.FocusedRowHandle > -1)
                //{
                //    selectedList.Add((UploadFile)view.GetRow(view.FocusedRowHandle));
                //}
                foreach (var item in selectedList)
                {
                    if (item.Status == FileUploadStatus.Finished && item.ServerFileModel != null)
                    {
                        FileUploadService.Instance.Delete(item.ServerFileModel.Url);
                        if (item.ServerFileModel.Id.IsNotEmpty())
                        {
                            FileService.Instance.Delete(item.ServerFileModel.Id);
                        }
                    }
                    data.Delete(p => p.Path.Equals(item.Path));
                }
                gridControl1.RefreshDataSource();
            }
            finally
            {
                SetButtonStatus();
                RemoveCompleted?.Invoke(this, new ImageEventArgs());
            }
        }

        /// <summary>
        /// 重置数据
        /// </summary>
        public void ResetData()
        {
            data.Clear();
            gridControl1.RefreshDataSource();
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        public void UploadFile(Action<FileUploadEventArgs> callback = null)
        {
            var args = new ImageBeforeEventArgs();
            BeforeUpload?.Invoke(this, args);
            if (args.Cancel)
            {
                return;
            }

            OverlayForm.Show(this);
            var successList = new List<UploadFile>();
            var failList = new List<UploadFile>();
            Stopwatch stopwatch = new Stopwatch();
            Task.Run(() =>
            {
                var waitingList = data.Where(p => p.Status == FileUploadStatus.Waiting).ToList();
                var finishTotalSize = 0L;

                stopwatch.Start();
                for (int i = 0; i < waitingList.Count; i++)
                {
                    var item = waitingList[i];
                    var fileInfo = new FileInfo(item.Path);
                    var result = FileUploadService.Instance.UploadFileAsMessage(UploadFolder, null, fileInfo.Name, fileInfo.FullName, p =>
                    {
                        item.Status = FileUploadStatus.Uploading;
                        item.Percentage = p.ProgressPercentage;

                        double duration = stopwatch.Elapsed.TotalSeconds;
                        double speed = (finishTotalSize + (item.Size * (p.ProgressPercentage / 100d))) / duration;
                        double totalProgress = (((i * 100) + p.ProgressPercentage) / (waitingList.Count * 100d)) * 100;
                        var msg = $"正在上传...\n总进度:{Math.Round(totalProgress, 0)}%, 当前进度:{p.ProgressPercentage}%, 平均速度:{XCI.Helper.StringHelper.GetSpaceSizeString(Convert.ToInt64(speed), "#######")}/秒";
                        OverlayForm.SetText(msg);
                        if (gridControl1.FocusedView is GridView)
                        {
                            gridView1.RefreshData();
                        }
                    });
                    item.ServerFileModel = result.Data;
                    if (result.Success)
                    {
                        item.Status = FileUploadStatus.Finished;
                        item.ServerFileModel = result.Data;
                        successList.Add(item);
                    }
                    else
                    {
                        item.Msg = result.Msg;
                        failList.Add(item);
                    }
                    finishTotalSize += item.Size;
                }
            }).ContinueWith(p =>
            {
                stopwatch.Stop();
                SetButtonStatus();
                if (AutoSaveToFileTable && editValue.IsNotEmpty() && successList.Count > 0)
                {
                    OverlayForm.SetText("正在保存附件信息...");
                    foreach (var item in successList)
                    {
                        FileService.Instance.Insert(item.ServerFileModel, editValue);
                    }
                }
                //if (failList.Count > 0)
                //{
                //    MessageBoxHelper.ShowError(failList.Select(x => x.Msg).JoinString('\n'));
                //}
                OverlayForm.Close();
                var iargs = new FileUploadEventArgs { SuccessList = successList, FailList = failList };
                callback?.Invoke(iargs);
                UploadCompleted?.Invoke(this, iargs);
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        public void ExportFile()
        {
            var args = new ImageBeforeEventArgs();
            BeforeExport?.Invoke(this, args);
            if (args.Cancel)
            {
                return;
            }

            if (folderDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    OverlayForm.Show(this);
                    OverlayForm.SetText("正在导出...");
                    foreach (var item in GetSelectedList())
                    {
                        var destPath = Path.Combine(folderDialog.SelectedPath, item.Name + item.ExtName);
                        File.Copy(item.Path, destPath, true);
                    }
                    ExportCompleted?.Invoke(this, new ImageEventArgs());
                    OverlayForm.Close();
                    MessageBoxHelper.ShowWarn("导出完成");
                }
                catch (Exception ex)
                {
                    MessageBoxHelper.ShowError("导出文件时出现错误");
                    DebugHelper.Catch(ex.Message);
                }
                finally
                {
                    OverlayForm.Close();
                }
            }
        }

        /// <summary>
        /// 文件属性
        /// </summary>
        public void PropertyFile()
        {
            var selected = GetSelected();
            DownloadFile(selected, () =>
            {
                FileSystemHelper.ShellExecuteFileInfo(selected.Path, ShellExecuteInfoFileType.Properties);
            });
        }

        public void DoubleClickFile(UploadFile uploadFile)
        {
            DownloadFile(uploadFile, () =>
            {
                if (uploadFile.IsImageFile)
                {
                    var fileList = data.Where(p => p.IsImageFile).Select(p => p.Path).ToList();
                    var imagePreview = new FrmImagePreview(fileList, uploadFile.Path);
                    imagePreview.Size = WinHelper.GetImagePreviewSize();
                    imagePreview.Show();
                }
                else
                {
                    FileSystemHelper.ShellExecuteFileInfo(uploadFile.Path, ShellExecuteInfoFileType.Open);
                }
            });
        }


        private void DownloadFile(UploadFile uploadFile, Action action)
        {
            var localPath = uploadFile.ServerFileModel == null ? uploadFile.Path : WinHelper.BuildLocalPathByServerPath(uploadFile.ServerFileModel.Url);
            if (File.Exists(localPath))
            {
                action?.Invoke();
            }
            else
            {
                OverlayForm.Show(this);
                Task.Run(() =>
                {
                    FileUploadService.Instance.Download(uploadFile.ServerFileModel.Url, localPath, null, p =>
                    {
                        OverlayForm.SetText($"正在下载... {p.ProgressPercentage.ToString()}%");
                    });
                }).ContinueWith(p =>
                {
                    var fileInfo = new FileInfo(localPath);
                    SetFileImage(uploadFile, fileInfo);
                    gridControl1.RefreshDataSource();
                    SetButtonStatus();
                    LoadCompleted?.Invoke(this, new ImageEventArgs());
                    OverlayForm.Close();
                    action?.Invoke();
                }, TaskScheduler.FromCurrentSynchronizationContext());
            }
        }

        /// <summary>
        /// 获取选中的对象
        /// </summary>
        public UploadFile GetSelected()
        {
            ColumnView view = (ColumnView)gridControl1.FocusedView;
            return (UploadFile)gridControl1.FocusedView.GetRow(view.FocusedRowHandle);
        }

        /// <summary>
        /// 获取选中的对象集合
        /// </summary>
        public List<UploadFile> GetSelectedList()
        {
            ColumnView view = (ColumnView)gridControl1.FocusedView;
            var indexs = view.GetSelectedRows();
            var list = new List<UploadFile>();
            foreach (var index in indexs)
            {
                list.Add((UploadFile)view.GetRow(index));
            }
            return list;
        }

        private bool GridViewHitTest(GridHitInfo calcHitInfo)
        {
            return calcHitInfo.HitTest == GridHitTest.Row || calcHitInfo.HitTest == GridHitTest.RowCell;
        }

        private bool ExplorerViewHitTest(WinExplorerViewHitInfo calcHitInfo)
        {
            return calcHitInfo.HitTest == WinExplorerViewHitTest.Item
                    || calcHitInfo.HitTest == WinExplorerViewHitTest.ItemCheck
                    || calcHitInfo.HitTest == WinExplorerViewHitTest.ItemText
                    || calcHitInfo.HitTest == WinExplorerViewHitTest.ItemImage
                    || calcHitInfo.HitTest == WinExplorerViewHitTest.ItemDescription;
        }

        private void FileUploadControl_Load(object sender, EventArgs e)
        {
            bar1.Visible = ToolbarVisable;
            OverlayForm.SetColor(Color.Blue);
            OverlayForm.SetFont(new Font(WindowsFormsSettings.DefaultFont.Name, WindowsFormsSettings.DefaultFont.Size + 4, FontStyle.Bold));
            SetViewMode(viewMode);
            BuildPopupMenuCore();
            gridControl1.DataSource = data;
        }

        private void BtnSelect_ItemClick(object sender, ItemClickEventArgs e)
        {
            SelectFile();
        }

        private void BtnRemove_ItemClick(object sender, ItemClickEventArgs e)
        {
            RemoveFile();
        }

        private void BtnUpload_ItemClick(object sender, ItemClickEventArgs e)
        {
            UploadFile();
        }

        private void BtnExport_ItemClick(object sender, ItemClickEventArgs e)
        {
            ExportFile();
        }

        private void BtnProperty_ItemClick(object sender, ItemClickEventArgs e)
        {
            PropertyFile();
        }

        private void BtnSwitchView_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (gridControl1.FocusedView is WinExplorerView)
            {
                SetViewMode(FileUploadGridViewMode.GridView);
            }
            else
            {
                SetViewMode(FileUploadGridViewMode.ExplorerView);
            }
        }

        private void GridControl1_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Copy;
        }

        private void GridControl1_DragDrop(object sender, DragEventArgs e)
        {
            var files = (string[])e.Data.GetData(DataFormats.FileDrop);
            if (files.Length <= 0) return;
            AddFile(files, FileUploadStatus.Waiting);
        }

        private void GridView1_SelectionChanged(object sender, DevExpress.Data.SelectionChangedEventArgs e)
        {
            SetButtonStatus();
        }

        private void GridView1_DoubleClick(object sender, EventArgs e)
        {
            var ev = (DXMouseEventArgs)e;
            var hitInfo = gridView1.CalcHitInfo(ev.Location);
            var selected = GetSelected();
            if (selected != null && ev.Clicks == 2 && ev.Button == MouseButtons.Left && GridViewHitTest(hitInfo))
            {
                DoubleClickFile(selected);
            }
        }

        private void GridView1_MouseUp(object sender, MouseEventArgs e)
        {
            var hitInfo = gridView1.CalcHitInfo(e.Location);
            if (e.Button == MouseButtons.Right && GridViewHitTest(hitInfo))
            {
                popupMenu1.ShowPopup(MousePosition);
            }
        }

        private void ExplorerView1_SelectionChanged(object sender, DevExpress.Data.SelectionChangedEventArgs e)
        {
            SetButtonStatus();
        }

        private void ExplorerView1_DoubleClick(object sender, EventArgs e)
        {
            var ev = (DXMouseEventArgs)e;
            var hitInfo = explorerView1.CalcHitInfo(ev.Location);
            var selected = GetSelected();
            if (selected != null && ev.Clicks == 2 && ev.Button == MouseButtons.Left && ExplorerViewHitTest(hitInfo))
            {
                DoubleClickFile(selected);
            }
        }

        private void ExplorerView1_MouseUp(object sender, MouseEventArgs e)
        {
            var hitInfo = explorerView1.CalcHitInfo(e.Location);
            if (e.Button == MouseButtons.Right && ExplorerViewHitTest(hitInfo))
            {
                popupMenu1.ShowPopup(MousePosition);
            }
        }

        private void GridView1_CustomSummaryCalculate(object sender, DevExpress.Data.CustomSummaryEventArgs e)
        {
            GridView view = sender as GridView;
            GridSummaryItem item = e.Item as GridSummaryItem;
            if (e.IsTotalSummary && item.FieldName == "Name")
            {
                switch (e.SummaryProcess)
                {
                    case CustomSummaryProcess.Start:
                        totalSize = 0;
                        totalCount = 0;
                        break;
                    case CustomSummaryProcess.Calculate:
                        long size = (long)view.GetRowCellValue(e.RowHandle, "Size");
                        totalSize += size;
                        totalCount++;
                        break;
                    case CustomSummaryProcess.Finalize:
                        if (totalCount > 0)
                        {
                            gridView1.OptionsView.ShowFooter = true;
                            e.TotalValue = $"共 {totalCount} 项,共 {XCI.Helper.StringHelper.GetSpaceSizeString(totalSize)}";
                        }
                        else
                        {
                            gridView1.OptionsView.ShowFooter = false;
                        }
                        break;
                }
            }
        }

    }

    public enum FileUploadGridViewMode
    {
        GridView,
        ExplorerView
    }
}
